package com.songlanyun.modules.account.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;

import com.songlanyun.common.enums.BillConstant;
import com.songlanyun.common.enums.IntegralConstant;
import com.songlanyun.common.utils.custom.MathUtils;
import com.songlanyun.common.utils.custom.PatternUtils;
import com.songlanyun.modules.account.dao.HandlingFeesDao;
import com.songlanyun.modules.account.entity.HandlingFeesEntity;
import com.songlanyun.modules.account.entity.UserVerifiedEntity;
import com.songlanyun.modules.account.model.dto.PointGiveAwayDTO;
import com.songlanyun.modules.account.model.vo.PointGiveAwayComputerVO;
import com.songlanyun.modules.account.service.UserVerifiedService;
import com.songlanyun.modules.integralrecord.entity.IntegralRecord;
import com.songlanyun.modules.integralrecord.service.IntegralRecordService;
import com.songlanyun.modules.memberbill.entity.SaleRefillVoucherBillEntity;
import com.songlanyun.modules.memberbill.service.SaleRefillVoucherBillService;
import com.songlanyun.modules.pointconfig.entity.PointConfig;
import com.songlanyun.modules.pointconfig.service.PointConfigService;
import com.songlanyun.modules.pointgiveaway.entity.PointGiveAwayEntity;
import com.songlanyun.modules.pointgiveaway.service.PointGiveAwayService;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;
import com.songlanyun.common.validator.ValidatorUtils;
import com.songlanyun.common.validator.group.AppGroup;
import com.songlanyun.modules.account.dao.UserIdentityAssetDao;
import com.songlanyun.modules.account.entity.AccountEntity;
import com.songlanyun.modules.account.entity.UserIdentityAssetEntity;
import com.songlanyun.modules.account.model.dto.SetUpPaymentPasswordDTO;
import com.songlanyun.modules.account.service.AccountService;
import com.songlanyun.modules.account.service.CommonService;
import com.songlanyun.modules.account.service.UserIdentityAssetService;
import com.songlanyun.modules.exception.MemberException;

import cn.hutool.core.util.ObjectUtil;
import org.springframework.transaction.annotation.Transactional;


@Service("yxtUserIdentityAssetService")
public class UserIdentityAssetServiceImpl extends ServiceImpl<UserIdentityAssetDao, UserIdentityAssetEntity> implements UserIdentityAssetService {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private AccountService accountService;

    @Resource
    private CommonService commonService;

    @Autowired
    private PointConfigService pointConfigService;

    @Autowired
    private IntegralRecordService integralRecordService;

    @Autowired
    private UserVerifiedService userVerifiedService;

    @Autowired
    private PointGiveAwayService pointGiveAwayService;

    @Autowired
    private UserIdentityAssetService userIdentityAssetService;

    @Autowired
    private SaleRefillVoucherBillService saleRefillVoucherBillService;

    @Autowired
    private HandlingFeesDao handlingFeesDao;




    public final static  String  PASS_SALT = "songheshop";

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UserIdentityAssetEntity> page = this.page(
                new Query<UserIdentityAssetEntity>().getPage(params),
                new QueryWrapper<UserIdentityAssetEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public int updateUserBalance(UserIdentityAssetEntity userIdentity) {
        return baseMapper.updateUserBalance(userIdentity);
    }


    /**
     * @param userId 用户id
     * @param money  金额
     * @param isAdd  true:收入 fasle:支出
     */
    @Override
    public UserIdentityAssetEntity updateBalance(Long userId, BigDecimal money, boolean isAdd) {

        UserIdentityAssetEntity userIdentity = null;

        userIdentity = this.loadByIdForLock(userId, true);
        if (isAdd) {//收入
            userIdentity.incBalance(money);//增加后的余额
        } else {//支出
            userIdentity.decBalance(money); //减少后的余额
        }
        this.updateById(userIdentity);

        return userIdentity;

    }

    @Override
    public void checkMoney(Long userId, BigDecimal money) {
        UserIdentityAssetEntity entity = this.loadByIdForLock(userId, true);
        if (entity.getBalance().compareTo(money) < 0) {
            throw new RRException(MemberException.NOT_SUFFICIENT_FUNDS);
        }
    }

    @Override
    public UserIdentityAssetEntity updateCommissionAble(Long userId, BigDecimal money, boolean isAdd) {

        UserIdentityAssetEntity userIdentity = null;
        userIdentity = this.loadByIdForLock(userId, true);
        if (isAdd) {//收入（会员分佣所得）
            userIdentity.incCommission(money);
        } else {//支出（会员分佣提现）
//            if (userIdentity.getCommissionAble().compareTo(money) < 0) {//可提现所得是否充足
//                throw new RRException(MemberException.NOT_SUFFICIENT_FUNDS);
//            }
            userIdentity.decCommission(money);
        }

        this.updateById(userIdentity);
        return userIdentity;
    }

    /**
     * 获取可提现金额
     *
     * @param userId
     * @return
     */
    @Override
    public BigDecimal getCommissionAble(Long userId) {
        UserIdentityAssetEntity userIdentityAsset = this.loadByIdForLock(userId, true);
        if (userIdentityAsset == null) {
            return BigDecimal.ZERO;
        }
        return userIdentityAsset.getCommissionAble();
    }

    @Override
    public UserIdentityAssetEntity getById(Long userId, boolean isThrow) {
        UserIdentityAssetEntity userIdentityAssetEntity = this.baseMapper.selectById(userId);
        if (userIdentityAssetEntity == null) {
            if (isThrow) {
                throw new RRException(MemberException.NOT_EXISTS);
            }
        }
        return userIdentityAssetEntity;
    }

    @Override
    public UserIdentityAssetEntity updateIntegral(Long userId, BigDecimal value, boolean isAdd) {
        UserIdentityAssetEntity userIdentity = this.loadByIdForLock(userId, true);
        if (isAdd) {//收入
            userIdentity.incIntegral(value);//增加后的积分
        } else {//支出
            userIdentity.decIntegral(value); //减少后的积分
        }
        this.updateById(userIdentity);

        return userIdentity;
    }

    @Override
    public UserIdentityAssetEntity loadByIdForLock(Long userId, boolean tw) {
        UserIdentityAssetEntity entity = this.baseMapper.loadByIdForLock(userId);
        if (entity == null && tw) {
            throw new RRException(MemberException.NOT_EXISTS);
        }
        return entity;
    }

    @Override
    public UserIdentityAssetEntity updateLoveValue(Long userId, Integer value, boolean isAdd) {
        UserIdentityAssetEntity userIdentity = this.loadByIdForLock(userId, true);
        if (isAdd) {
            //收入
            userIdentity.setLoveValue(userIdentity.getLoveValue() + value);
            userIdentity.setCumulativeLoveValue(userIdentity.getCumulativeLoveValue() + value);
        } else {
            //支出
            if (userIdentity.getLoveValue() < value) {
                //爱心不足
                throw new RRException(MemberException.YOUR_LOVE_VALUE_IS_INSUFFICIENT);
            }
            userIdentity.setLoveValue(userIdentity.getLoveValue() - value);
        }
        this.updateById(userIdentity);
        return userIdentity;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setUpPaymentPassword(SetUpPaymentPasswordDTO dto) {
        // 校验
        ValidatorUtils.validateEntity(dto, AppGroup.class);
        Long userId = dto.getUserId();
        AccountEntity entity = accountService.getUserById(userId, true);
        // 检查验证码是否正确
        commonService.checkVerCode(entity.getMobile(), dto.getCaptcha());
        UserIdentityAssetEntity userIdentityAssetEntity = baseMapper.loadByIdForLock(userId);
        if (ObjectUtil.isNotNull(userIdentityAssetEntity)) {
            String payPass = dto.getPayPass();
            //sha256加密
            String newPayPassEnc = new Sha256Hash(payPass, PASS_SALT).toHex();
            userIdentityAssetEntity.setPayPass(newPayPassEnc);
            baseMapper.updateById(userIdentityAssetEntity);
        }

    }

    @Override
    public BigDecimal countAllActivationUseCommissionAble() {
        return this.baseMapper.countAllActivationUseCommissionAble();
    }


    /**
     * 积分转赠
     * @param userId
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void pointGiveAway(Long userId, PointGiveAwayDTO dto) {
        AccountEntity account = accountService.getUserById(userId, true);
        AccountEntity accounted = accountService.getUserById(dto.getUserObjId(), true);

        if(userId.equals(dto.getUserObjId()))
        {
            throw new RRException("不能转赠给自己");
        }

        UserVerifiedEntity  optionUserVerifiedEntity = userVerifiedService.loadById(userId, false);
        if(ObjectUtil.isNull(optionUserVerifiedEntity))
        {
            throw new RRException("您还没有实名认证不能转赠");
        }
        UserVerifiedEntity userVerifiedEntity = userVerifiedService.loadById(dto.getUserObjId(), false);
        if(ObjectUtil.isNull(userVerifiedEntity))
        {
            throw new RRException("被转赠的用户没有实名认证");
        }

        UserIdentityAssetEntity optionUserAssetEntity = this.loadByIdForLock(userId, true);
        String pass = new Sha256Hash(dto.getPayPassword(), PASS_SALT).toHex();

        if(ObjectUtil.isEmpty(optionUserAssetEntity.getPayPass()))
        {
            throw new RRException("支付密码没设置",99999);
        }


        if(!optionUserAssetEntity.getPayPass().equals(pass))
        {
            throw new RRException("支付密码错误");
        }

        if(optionUserAssetEntity.getIntegralAble().compareTo(dto.getValue())<0)
        {
            throw new RRException("您的可用积分不足");
        }


        PointConfig config = pointConfigService.loadConfig(true);

        BigDecimal giveAwayHandlingFeeRatio = config.getGiveAwayHandlingFeeRatio();
        BigDecimal handlingFee = MathUtils.setScaleDown(dto.getValue().doubleValue() * giveAwayHandlingFeeRatio.doubleValue() / 100, 8);
        BigDecimal facePoint = MathUtils.setScaleDown(dto.getValue().doubleValue()-handlingFee.doubleValue(),8);

        //当前积分价格
        BigDecimal pointPrice = config.getPointPrice();
        //转账用户
        UserIdentityAssetEntity userIdentityAsset = userIdentityAssetService.getById(userId,true);
        //当前的兑换券余额
        BigDecimal voucher = userIdentityAsset.getVoucher();
        if (voucher == null){
            voucher = BigDecimal.ZERO;
        }
        //根据当时市场价换算后的兑换券数量
        BigDecimal bigDecimal = handlingFee.multiply(pointPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
        //加完后的兑换券余额
        BigDecimal addVoucher = voucher.add(bigDecimal);
        userIdentityAsset.setVoucher(addVoucher);
        userIdentityAssetService.updateById(userIdentityAsset);

        SaleRefillVoucherBillEntity bill = new SaleRefillVoucherBillEntity();
        bill.setRemark("积分余额(消费额余额)");//账单说明
        bill.setBillType(BillConstant.BillMode.INCOME);//账单类型
        bill.setEntryBeforeBalance(voucher);//入帐前的余额
        bill.setEntryAfterBalance(addVoucher);//入帐后的余额
        bill.setEntryValue(bigDecimal);//入帐的额度
//        bill.setSaleOrderCode(outTradeNo);//消费订单编号
        bill.setInnerMode(BillConstant.InnerMode.POINT_CONVERSION);//支出（0普通消费）
        bill.setCreateTimeMillis(System.currentTimeMillis());//创建帐户的时间戳
        bill.setUserId(userId);//会员id
        saleRefillVoucherBillService.save(bill);


        //转赠人转出
        integralRecordService.outer(userId, dto.getValue(), IntegralConstant.OuterMode.OUTER_POINT_GIVE_AWAY,
                IntegralConstant.IntegralModelType.POINT_GIVE_AWAY, userId, String.format("积分转赠给%s",userVerifiedEntity.getRealName()));

        //被转赠人转入
        IntegralRecord integralRecord = new IntegralRecord(dto.getUserObjId(), facePoint, IntegralConstant.InnerMode.INNER_POINT_GIVE_AWAY,
                IntegralConstant.IntegralModelType.POINT_GIVE_AWAY, dto.getUserObjId(), String.format("用户%s(%s)转赠积分",optionUserVerifiedEntity.getRealName(), PatternUtils.insensitiveOfPhone(account.getMobile())));
        integralRecordService.inner(integralRecord);


        PointGiveAwayEntity pointGiveAwayEntity = new PointGiveAwayEntity();
        pointGiveAwayEntity.setGiveUserId(userId);
        pointGiveAwayEntity.setGiveRealName(optionUserVerifiedEntity.getRealName());
        pointGiveAwayEntity.setGiveMobile(account.getMobile());

        pointGiveAwayEntity.setAcceptUserId(dto.getUserObjId());
        pointGiveAwayEntity.setAcceptRealName(userVerifiedEntity.getRealName());
        pointGiveAwayEntity.setAcceptMobile(accounted.getMobile());

        pointGiveAwayEntity.setGivePoint(dto.getValue());

        //手续费的30%进入销毁池
        BigDecimal handlingFee2 = MathUtils.setScaleDown(handlingFee.doubleValue() * 0.3, 8);
        //进入到公司总账
        BigDecimal handlingFee3 = MathUtils.setScaleDown(handlingFee.doubleValue() * 0.7, 8);

        HandlingFeesEntity handlingFeesEntity = new HandlingFeesEntity();
        handlingFeesEntity.setHandlingFee(handlingFee3);
        handlingFeesEntity.setUserId(userId);
        handlingFeesEntity.setCreatTime(new Date());
        handlingFeesDao.insert(handlingFeesEntity);

        pointGiveAwayEntity.setHandlingFee(handlingFee2);
        pointGiveAwayEntity.setFacePoint(facePoint);
        pointGiveAwayService.create(pointGiveAwayEntity);

    }

    @Override
    public PointGiveAwayComputerVO pointGiveAwayComputer(Long userId, PointGiveAwayDTO dto) {
        UserVerifiedEntity  optionUserVerifiedEntity = userVerifiedService.loadById(userId, false);
        if(ObjectUtil.isNull(optionUserVerifiedEntity))
        {
            throw new RRException("您还没有实名认证不能转赠");
        }

        UserIdentityAssetEntity optionUserAssetEntity = this.loadByIdForLock(userId, true);
        if(optionUserAssetEntity.getIntegralAble().compareTo(dto.getValue())<0)
        {
            throw new RRException("您的可用积分不足");
        }



        PointConfig config = pointConfigService.loadConfig(true);

        BigDecimal giveAwayHandlingFeeRatio = config.getGiveAwayHandlingFeeRatio();
        BigDecimal handlingFee = MathUtils.setScaleDown(dto.getValue().doubleValue() * giveAwayHandlingFeeRatio.doubleValue() / 100, 8);
        BigDecimal facePoint = MathUtils.setScaleDown(dto.getValue().doubleValue()-handlingFee.doubleValue(),8);
        return PointGiveAwayComputerVO.builder().handlingFee(handlingFee).facePoint(facePoint).build() ;
    }

    @Override
    public UserIdentityAssetEntity updateVoucher(Long userId, BigDecimal money, boolean isAdd) {
        UserIdentityAssetEntity userIdentity = null;

        userIdentity = this.loadByIdForLock(userId, true);
        if (isAdd) {//收入
            userIdentity.incVoucher(money);//增加后的余额

        } else {//支出
            userIdentity.decVoucher(money); //减少后的余额
        }
        this.updateById(userIdentity);

        return userIdentity;
    }


}
